

#region Copyright (c) 2004, 2005 Quantum Whale LLC.
/*
	Quantum Whale .NET Component Library
	Editor.NET Syntax Demo

	Copyright (c) 2004 Quantum Whale LLC.
	ALL RIGHTS RESERVED

	http://www.qwhale.net
	contact@qwhale.net
*/
#endregion Copyright (c) 2004 Quantum Whale LLC.

using System;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Drawing;
using System.Resources;
using System.IO;
using System.Xml.Serialization;
using QWhale.Common;
using QWhale.Syntax.Parsers;
using QWhale.Syntax.CodeCompletion;

namespace QWhale.Syntax
{

    public class CsClassBodyParser : CsParser
    {
        private string namespaceName = string.Empty;
        private string className = string.Empty;

        public CsClassBodyParser(string namespaceName, string className)
        {
            this.namespaceName = namespaceName;
            this.className = className;
        }

        protected override bool SkipToDeclarationStart(int nodeType)
        {
            if (nodeType == (int)NetNodeType.Class)
                return true;
            else
                return SkipTo((int)CsLexerToken.Open_brace);
        }
        //protected override bool ParseDeclarationBodyEnd(ISyntaxNode node)
        //{
        //    return (node.NodeType == (int)NetNodeType.Class) ? true : Expected(CsLexerToken.Close_brace);
        //}

        protected override bool ParseDeclarationBody(ISyntaxNode node, int
nodeType)
        {
            bool result = true;
            Point pos = TokenPosition;
            SyntaxTree.Push(node);
            bool block = false;
            try
            {
                block = SkipToDeclarationStart(nodeType);
                if (block)
                {
                    node.AddAttribute(new SyntaxAttribute(pos,
SyntaxConsts.DefinitionScope, null));
                    node.Options |= SyntaxNodeOptions.Outlining |
SyntaxNodeOptions.Indentation;
                    if (Token == (int)CsLexerToken.Open_brace)
                        MoveNext();
                    switch ((NetNodeType)node.NodeType)
                    {
                        case NetNodeType.Namespace:
                        case NetNodeType.Class:
                        case NetNodeType.Struct:
                        case NetNodeType.Interface:
                            {
                                if (!ParseClassBody())
                                    result = false;
                                break;
                            }
                        case NetNodeType.Enum:
                            {
                                if (!ParseEnumBody())
                                    result = false;
                                break;
                            }
                        default:
                            {
                                result = false;
                                break;
                            }
                    }
                }
            }
            finally
            {
                SyntaxTree.Pop();
            }
            if (block && ParseDeclarationBodyEnd(node))
            {
                node.AddAttribute(new SyntaxAttribute(prevPosition,
SyntaxConsts.DefinitionScopeEnd, null));
                if (Token == (int)CsLexerToken.Semicolon)
                    MoveNext();
            }
            else
                result = false;
            return result;
        }
        protected bool ParseEmptyClass()
        {
            bool result = true;
            ISyntaxNode namespacenode = new SyntaxNode(TokenPosition,
TokenString, (int)NetNodeType.Namespace, SyntaxNodeOptions.BackIndentation);
            namespacenode.Name = namespaceName;
            namespacenode.Options |= SyntaxNodeOptions.CodeCompletion;
            ISyntaxNode node = new SyntaxNode(TokenPosition, TokenString,
(int)NetNodeType.Class, SyntaxNodeOptions.BackIndentation);
            node.Name = className;
            node.Options |= SyntaxNodeOptions.CodeCompletion;
            node.AddAttribute(new SyntaxAttribute(TokenPosition,
NetNodeType.Modifier.ToString(), SyntaxParserConsts.PartialModifier));
            AddNode(namespacenode);
            SyntaxTree.Push(namespacenode);
            try
            {
                AddNode(node);
                SyntaxTree.Push(node);
                try
                {
                    if (!ParseClassBody())
                        //if (!ParseDeclarationBody(node,(int)NetNodeType.Class))
                        result = false;
                }
                finally
                {
                    SyntaxTree.Pop();
                }
                //node.Range.EndPoint = new Point(int.MaxValue,int.MaxValue);
                node.Range.EndPoint = new Point(TokenPosition.X, TokenPosition.Y + 1);
            }
            finally
            {
                SyntaxTree.Pop();
            }
            //namespacenode.Range.EndPoint = new Point(int.MaxValue,int.MaxValue); ;
            namespacenode.Range.EndPoint = new Point(TokenPosition.X, TokenPosition.Y
+ 1);
            return result;
        }

        protected override bool ParseUnit()
        {
            bool result = true;
            ISyntaxNode node = SyntaxTree.Root;
            node.NodeType = (int)NetNodeType.Unit;
            node.Position = Point.Empty;
            result = ParseEmptyClass();
            SyntaxTree.Root.Range.EndPoint = prevPosition;

            if (!ClearStack())
                result = false;
            if (!FixupRegions(SyntaxTree.Current))
                result = false;
            return result;
        }
//        protected override int GetSmartIndent(ISyntaxNodes nodes, int index, bool
//autoIndent)
//        {
//            int result = base.GetSmartIndent(nodes, index, autoIndent);
//            result = Math.Max(0, result);
//            return result + 2;
//        }
    }

    public class CsMethodBodyParser : CsParser
    {
        private string namespaceName = string.Empty;
        private string className = string.Empty;
        private string methodName = string.Empty;
        private string methodParameters = string.Empty;

        public CsMethodBodyParser(string namespaceName, string className,
string methodName, string methodParameters)
        {
            this.namespaceName = namespaceName;
            this.className = className;
            this.methodName = methodName;
            this.methodParameters = methodParameters;
        }
        protected bool ParseEmptyClass()
        {
            bool result = true;
            Point pos = new Point(-1, -1);
            ISyntaxNode namespacenode = new SyntaxNode(pos, TokenString,
(int)NetNodeType.Namespace, SyntaxNodeOptions.BackIndentation);
            namespacenode.Name = namespaceName;
            namespacenode.Options |= SyntaxNodeOptions.CodeCompletion;
            ISyntaxNode node = new SyntaxNode(pos, TokenString,
(int)NetNodeType.Class, SyntaxNodeOptions.BackIndentation);
            node.Name = className;
            node.Options |= SyntaxNodeOptions.CodeCompletion;
            node.AddAttribute(new SyntaxAttribute(TokenPosition,
NetNodeType.Modifier.ToString(), SyntaxParserConsts.PartialModifier));
            AddNode(namespacenode);
            SyntaxTree.Push(namespacenode);
            try
            {
                AddNode(node);
                SyntaxTree.Push(node);
                try
                {
                    if (!ParseEmptyMethod())
                        result = false;
                }
                finally
                {
                    SyntaxTree.Pop();
                }
                //node.Range.EndPoint = new Point(int.MaxValue,int.MaxValue);
                node.Range.EndPoint = new Point(TokenPosition.X, TokenPosition.Y + 1);
            }
            finally
            {
                SyntaxTree.Pop();
            }
            //            namespacenode.Range.EndPoint = new Point(int.MaxValue,int.MaxValue); ;
            namespacenode.Range.EndPoint = new Point(TokenPosition.X, TokenPosition.Y
+ 1);
            return result;
        }
        private bool ParseParameterDeclaration(string parameter)
        {
            string param = parameter.Trim();
            int i = param.IndexOf(' ');
            bool result = true;
            ISyntaxNode node = new SyntaxNode(new Point(-1, -1),
string.Empty, (int)NetNodeType.Parameter, SyntaxNodeOptions.CodeCompletion);
            if (i >= 0)
            {
                string type = param.Substring(0, i).Trim();
                string identifier = param.Substring(i).Trim();
                node.Name = identifier;
                node.AddAttribute(new SyntaxAttribute(new Point(-1, -1),
NetNodeType.Type.ToString(), type));
                AddNode(node);
            }
            else
                result = false;
            node.Range.EndPoint = new Point(-1, -1);
            return result;
        }
        protected override bool ParseParameterListDeclaration()
        {
            bool result = true;
            ISyntaxNode node = new SyntaxNode(new Point(-1, -1),
string.Empty, (int)NetNodeType.ParameterList);
            AddNode(node);
            SyntaxTree.Push(node);
            try
            {
                string[] parameters = methodParameters.Split(';');
                for (int i = 0; i < parameters.Length; i++)
                {
                    ParseParameterDeclaration(parameters[i]);
                }
            }
            finally
            {
                SyntaxTree.Pop();
            }
            node.Range.EndPoint = new Point(-1, -1);
            return result;
        }
        protected bool ParseEmptyMethod()
        {
            bool result = true;
            ISyntaxNode node = new SyntaxNode(TokenPosition, string.Empty,
(int)NetNodeType.Method, SyntaxNodeOptions.BackIndentation);
            node.Name = methodName;
            node.Options |= SyntaxNodeOptions.CodeCompletion |
SyntaxNodeOptions.Outlining | SyntaxNodeOptions.Indentation;
            AddNode(node);

            SyntaxTree.Push(node);
            try
            {
                if (!ParseParameterListDeclaration())
                    result = false;
                if (!ParseMethodBody())
                    result = false;
            }
            finally
            {
                SyntaxTree.Pop();
            }

            //node.Range.EndPoint = new Point(int.MaxValue, int.MaxValue);
            node.Range.EndPoint = new Point(TokenPosition.X, TokenPosition.Y
+ 1);
            return result;
        }
        protected override bool ParseMethodBody()
        {
            bool result = true;
            if (!ParseBlockStatement())
                result = false;
            return result;
        }
        public override bool ReparseBlock(Point position, string text, out
ISyntaxNode node, CodeCompletionType completionType)
        {
            ReparseText();
            node = GetNodeAt(position);
            return node != null;
        }
        protected override bool ParseBlockStatement(ISyntaxAttributes attrs,
SyntaxNodeOptions options)
        {
            bool result = false;
            ISyntaxNode node = new SyntaxNode(TokenPosition, string.Empty,
(int)NetNodeType.BlockStatement, options);
            AddNode(node);
            if (attrs != null)
                node.AddAttributes(attrs);
            SyntaxTree.Push(node);
            try
            {
                result = ParseBlock();
            }
            finally
            {
                SyntaxTree.Pop();
            }
            node.Range.EndPoint = new Point(TokenPosition.X, TokenPosition.Y
+ 1);
            ISyntaxAttribute attr =
node.FindAttribute(SyntaxConsts.DefinitionScope);
            if (attr != null)
                AddAttribute(attr);
            attr = node.FindAttribute(SyntaxConsts.DefinitionScopeEnd);
            if (attr != null)
                AddAttribute(attr);
            return result;
        }
        protected override bool ParseBlock()
        {
            bool result = true;
            Point pos = TokenPosition;
            bool isExpected = false;
            if (Token == (int)CsLexerToken.Open_brace)
            {
                MoveNext();
                isExpected = true;
            }

            AddAttribute(new SyntaxAttribute(pos, SyntaxConsts.BlockScope,
null));
            AddAttribute(new SyntaxAttribute(pos,
SyntaxConsts.DefinitionScope, null));

            if (Token != (int)CsLexerToken.Close_brace)
            {
                if (!ParseStatementList())
                    result = false;
            }
            if (isExpected)
                if (Expected(CsLexerToken.Close_brace))
                    AddAttribute(new SyntaxAttribute(prevPosition,
SyntaxConsts.DefinitionScopeEnd, null));
                else
                    result = false;
            return result;
        }
        protected override bool ParseUnit()
        {
            bool result = true;
            ISyntaxNode node = SyntaxTree.Root;
            node.NodeType = (int)NetNodeType.Unit;
            node.Position = Point.Empty;
            result = ParseEmptyClass();
            SyntaxTree.Root.Range.EndPoint = prevPosition;

            if (!ClearStack())
                result = false;
            if (!FixupRegions(SyntaxTree.Current))
                result = false;
            return result;
        }
//        protected override int GetSmartIndent(ISyntaxNodes nodes, int index, bool
//autoIndent)
//        {
//            int result = base.GetSmartIndent(nodes, index, autoIndent);
//            result = Math.Max(0, result);
//            return result + 3;
//        }
    }
}
